#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <functional>
#include <sys/wait.h>
#include "Task.hpp"
#include "Channel.hpp"

// typedef function<void()> work_t;
using work_t = function<void()>;

enum
{
    Ok = 0,
    UsageError,
    PipeError,
    ForkError
};

class ProcessPool
{
public:
    ProcessPool(int n, work_t w)
        : processnum(n)
        , work(w)
    {}

    // channels 输出型参数
    // work_t work 回调
    int InitProcessPool()
    {
        for (int i = 0; i < processnum; i++)
        {
            // 1.先有管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
            {
                // 创建管道失败
                return PipeError;
            }
            // 2.创建指定个数的进程worker
            pid_t id = fork();
            if (id < 0)
            {
                return ForkError;
            }
            // 3.建立通信管道
            if (id == 0)
            {
                //在子进程关闭历史wfd
                //channels保存的是历史上master的写端
                std::cout<<getpid()<<"子进程关闭的历史fd";
                for(auto &c : channels)
                {
                    std::cout<<c.Wfd()<<" ";
                    c.Close();
                }
                std::cout<<"over"<<endl;

                ::close(pipefd[1]); // 子进程读read
                // child
                // 从标准输入读
                dup2(pipefd[0], 0);
                work();
                exit(0);
            }

            // 父进程执行
            ::close(pipefd[0]); // 父进程写 write
            channels.emplace_back(pipefd[1], id);
            // Channel ch(pipefd[1],id);
            // channels.push_back(ch);
        }
        return Ok;
    }

    // 派发任务
    void DispatchTask()
    {

        int n = 20;
        while (n--)
        {
            // 1.选择一个任务（数字）
            int task = tm1.SelectTask();
            // 2.选择一个子进程
            int who = 0;
            Channel &curr = channels[who++];
            who %= channels.size();

            cout << "#############################" << endl;
            cout << "send " << task << " to " << curr.Name() << ",任务还剩：" << n << endl;
            cout << "#############################" << endl;

            // 3.派发任务
            curr.Send(task);

            sleep(1);
        }
    }

    void CleanProcesspool()
    {
        // version 3 每建一个新的管道，将子进程中的写端关闭
        for(auto &c : channels)
        {
            c.Close();
            pid_t rid = ::waitpid(c.Id(), nullptr, 0);
            if (rid > 0)
            {
                cout << "child " << rid << "回收进程成功..." << endl;
            }
        }

        // version 2
        //for(auto &c : channels)
        // for(int i = channels.size()-1;i>=0;i--)
        // {
        //     channels[i].Close();
        //     pid_t rid = ::waitpid(channels[i].Id(), nullptr, 0);//阻塞了，可以倒着遍历
        //     if (rid > 0)
        //     {
        //         cout << "child " << rid << "回收进程成功..." << endl;
        //     }
        // }

        // version 1
        // for (auto &c : channels)
        // {
        //     
        // }
        // for (auto &c : channels)
        // {
        //     pid_t rid = ::waitpid(c.Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         cout << "child " << rid << "回收进程成功..." << endl;
        //     }
        // }
    }

    void DebugPront()
    {
        for (auto &c : channels)
        {
            cout << c.Name() << endl;
        }
    }

private:
    std::vector<Channel> channels;
    int processnum;
    work_t work;
};
